<?php



namespace app\common\logic;


use app\common\library\enum\CodeEnum;
use app\common\library\exception\OrderException;
use think\Db;
use think\Log;
use app\common\library\enum\OrderStatusEnum;

class Orders extends BaseLogic
{
    public function getOrderStatNew($where = [], $field = true, $order = 'a.create_time desc', $paginate = false)
    {
        $field = 'sum(1) as totalCount, sum(a.amount) as totalAmount, 
        sum(case when a.status = 1 then 1 else 0 end) as submitCount, sum(case when a.status = 1 then a.amount else 0 end) as submitAmount, 
        sum(case when a.status = 2 then 1 else 0 end) as payCount, sum(case when a.status = 2 then a.amount else 0 end) as payAmount, 
        sum(case when a.status = 0 then 1 else 0 end) as rejectCount, sum(case when a.status = 0 then a.amount else 0 end) as rejectAmount, 
        sum(case when a.status = 2 then a.amount - a.user_in else 0 end) as rateAmount';

        $this->modelOrders->alias('a');

        $prefix = config('database')['prefix'];
        $join = [
            [ $prefix . 'pay_code b', 'b.name = a.channel', 'left'],
            [ $prefix . 'pay_account c', 'c.id = a.cnl_id', 'left'],
            [ $prefix . 'pay_channel d', 'd.id = c.cnl_id', 'left'],
            [ $prefix . 'user u', 'u.uid = a.uid', 'left']
        ];

        $this->modelOrders->join = $join;
        $this->modelOrders->limit = !$paginate;
        return $this->modelOrders->getList($where, $field, $order, $paginate);
    }

    public function getOrderListNew($where = [], $field = true, $order = 'a.create_time desc', $paginate = 15)
    {
        $field = 'a.*,a.status as status2, u.username as uidName, b.name as payName, b.remarks as payRemarks, d.name as channelName';
        $this->modelOrders->alias('a');

        $prefix = config('database')['prefix'];
        $join = [
            [ $prefix . 'pay_code b', 'b.name = a.channel', 'left'],
            [ $prefix . 'pay_account c', 'c.id = a.cnl_id', 'left'],
            [ $prefix . 'pay_channel d', 'd.id = c.cnl_id', 'left'],
            [ $prefix . 'user u', 'u.uid = a.uid', 'left']
        ];

        $this->modelOrders->join = $join;
        $this->modelOrders->limit = !$paginate;
        return $this->modelOrders->getList($where, $field, $order, $paginate);
    }

    /**
     *
     * 获取订单列表
     *
     * @param array $where
     * @param bool $field
     * @param string $order
     * @param int $paginate
     * @return mixed
     */
    public function getOrderList($where = [], $field = true, $order = 'create_time desc', $paginate = 15)
    {
        $this->modelOrders->limit = !$paginate;
        return $this->modelOrders->getList($where, $field, $order, $paginate);
    }


    /**
     * 获取订单信息
     *
     *
     * @param array $where
     * @param bool|string $field
     *
     * @return mixed
     */
    public function getOrderInfo($where = [], $field = true)
    {
        return $this->modelOrders->getInfo($where, $field);
    }

    /**
     * 获取订单异步信息
     *
     *
     * @param array $where
     * @param bool $field
     *
     * @return mixed
     */
    public function getOrderNotify($where = [], $field = true)
    {
        return $this->modelOrdersNotify->getInfo($where, $field);
    }

    /**
     * 获取单总数
     *
     *
     * @param $where
     * @return mixed
     */
    public function getOrdersCount($where = [])
    {
        return $this->modelOrders->getCount($where);
    }

    /**
     * 订单统计
     *
     *
     * @param array $where
     * @return array
     */
    public function getOrdersAllStat($where = [])
    {
        return [
            'fees' => $this->modelOrders->getInfo($where, "COALESCE(sum(amount),0) as total,COALESCE(sum(if(status=2,amount,0)),0) as paid,COALESCE(sum(user_in),0) as user,COALESCE(sum(agent_in),0) as agent,COALESCE(sum(platform_in),0) as platform")
        ];
    }

    /**
     * 获取控制台统计
     *
     *
     * @param array $where
     * @return array
     */
    public function getWelcomeStat($where = [])
    {
        $order = 'create_time desc';
        $orderStat = $this->modelOrders->getInfo($where, "count(id) as total,count(if(status=2,true,null)) as success,count(if(status=1,true,null)) as wait,count(if(status=0,true,null)) as failed,COALESCE(sum(amount),0) as fees,COALESCE(sum(if(status=1,amount,0)),0) as unpaid,COALESCE(sum(if(status=2,amount,0)),0) as paid", $order, $paginate = false);
        $total = $orderStat['success'] + $orderStat['wait'];

        return [
            'order' => $orderStat,
            'user'  => $this->modelUser->getInfo($where, "count(uid) as total,count(if(is_verify=0,true,null)) as failed", $order, $paginate = false),
            'cash' => $this->modelBalanceCash->getInfo($where, 'count(id) as total,count(if(status=2,true,null)) as success,count(if(status=1,true,null)) as wait,COALESCE(sum(if(status=0,amount,0)),0) as failed', $order, $paginate = false),
            'fees' => $this->modelOrders->getInfo($where, "COALESCE(sum(amount),0) as total,COALESCE(sum(if(status=2,amount,0)),0) as paid"),
            'successRate' => $total > 0 ? bcdiv($orderStat['success'], $total, 4) * 100 : 0
        ];
    }

    /**
     * 年月订单以及交易额统计
     *
     *
     * @param array $where
     * @return array|mixed
     */
    public function getOrdersMonthStat($where = [])
    {
        $this->modelOrders->group = 'month';
        return $this->modelOrders->getList($where, "count(id) as total_orders,COALESCE(sum(`amount`),0) as total_amount,FROM_UNIXTIME(create_time,'%m') as month", false, false);
    }

    /**
     * 日订单以及交易额统计
     */
    public function getOrdersDayStat($where = [])
    {
        $this->modelOrders->group = 'day';
        return $this->modelOrders->getList($where, "count(id) as total_orders, COALESCE(sum(`amount`),0) as total_amount,FROM_UNIXTIME(create_time, '%d') as day", false, false);
    }

    /**
     * 订单以及交易额统计
     */
    public function getOrdersStat($format, $where = [])
    {
        $this->modelOrders->group = 'time';
        return $this->modelOrders->getList($where, "count(id) as total_orders, COALESCE(sum(`amount`),0) as total_amount,FROM_UNIXTIME(create_time, '%{$format}') as `time`", false, false);
    }

    /**
     * 获取商户订单统计
     *
     *
     * @param array $where
     * @param string $field
     * @param string $order
     * @param int $paginate
     * @return mixed
     */
    public function getOrderUserStat($where = [], $field = "uid,count(uid) as total_orders,COALESCE(sum(amount),0) as total_fee_all,COALESCE(sum(if(status=1,amount,0)),0) as total_fee_dis,COALESCE(sum(if(status=2,amount,0)),0) as total_fee_paid", $order = 'create_time desc', $paginate = 15)
    {
        $this->modelOrders->group = 'uid';
        return $this->modelOrders->getList($where, $field, $order, $paginate = false);
    }

    /**
     * 获取渠道订单统计
     *
     *
     * @param array $where
     * @param string $field
     * @param string $order
     * @param int $paginate
     * @return mixed
     */
    public function getOrderChannelStat($where = [], $field = "a.cnl_id,count(a.cnl_id) as total_orders,COALESCE(sum(a.amount),0) as total_fee_all,COALESCE(sum(if(a.status = 1,a.amount,0)),0) as total_fee_dis,COALESCE(sum(if(a.status = 2,a.amount,0)),0) as total_fee_paid,b.id,b.name,b.remarks,b.daily,b.rate", $order = '', $paginate = 15)
    {
        $this->modelOrders->group = 'a.cnl_id';
        $this->modelOrders->alias('a');

        $prefix = config('database')['prefix'];
        $join = [
            [ $prefix . 'pay_account b', ' b.id = a.cnl_id']
        ];

        $this->modelOrders->join = $join;
        $res = $this->modelOrders->getList($where, $field, $order, $paginate = false);
        return $res;
    }

    /**
     * 获取某订单支付通道配置
     *
     *
     * @param $order_no
     * @return mixed
     */
    public function getOrderPayConfig($order_no)
    {

        return $this->logicPay->getAccountInfo(
            [
                'id'    => $this->modelOrders->getValue(['trade_no' => $order_no], 'cnl_id')
            ]
        );
    }

    /**
     * 推送队列
     *
     *
     * @param $order_id
     * @return array
     */
    public function pushOrderNotify($order_id = '')
    {
        //订单
        $order = $this->getOrderInfo(['id' => $order_id]);
        //加入队列
        $result = $this->logicQueue->pushJobDataToQueue('AutoOrderNotify', $order, 'AutoOrderNotify');
        if ($result) {
            $returnmsg = ['code' =>  CodeEnum::SUCCESS, 'msg'  => '推送队列成功'];
        } else {
            $returnmsg = ['code' =>  CodeEnum::SUCCESS, 'msg'  => '推送队列成功'];
        }
        action_log('推送', '推送异步订单通知，单号：' . $order['out_trade_no']);
        return $returnmsg;
    }

    /**
     * 计算不在amounts中最接近amount的价格
     * 
     * @param float $amount
     * @param array $amounts
     * @return float
     */
    public function computeAmount($amount, $amounts)
    {
        for($i = 0; $i < 10; $i ++) 
        {
            if (!in_array($amount, $amounts)) {
                return $amount;
            }

            $amount = bcsub($amount, 0.01, 2);
            if ($amount < 0.01) {
                break;
            }
        }

        throw new OrderException([
            'msg' => "没有可用的固码金额",
            'errCode' => 4004,
        ]);
    }

    /**
     * 创建支付订单
     *
     *
     * @param $orderData
     * @return mixed
     * @throws OrderException
     */
    public function createPayOrder($orderData)
    {
        //TODO 事务处理
        $payAmount = 0.00;
        if ($orderData['pay_type'] == "G0071")
        {
            //如果是固码支付，则修改实际支付金额
            $createTime = time() - 60 * 10; //十分钟内
            $where = "`channel` = 'G0071' && `create_time` > {$createTime} && `pay_amount` <= {$orderData['order_amt']} && `status` = " . OrderStatusEnum::UNPAID;

            $result = $this->modelOrders->query("SELECT `pay_amount` FROM `pay_orders` WHERE {$where} ORDER BY `id` DESC LIMIT 100");
            $amounts = [];
            foreach($result as $item) {
                $amounts[] = $item['pay_amount'];
            }
            
            $amount = $this->computeAmount($orderData['order_amt'], $amounts);
            $payAmount = $amount;
        }

        Db::startTrans();
        try {

            $orderNo = create_order_no();
            while ($this->getOrderInfo(['trade_no' => $orderNo]) != null) {
               $orderNo = create_order_no();
            }

            //这里就这样   不改了
            $order = new Orders();
            $order->uid         = $orderData['app_id']; //商户ID
            $order->subject     = !empty($orderData['goods_name']) ? urldecode($orderData['goods_name']) : ""; //支付项目
            $order->body        = !empty($orderData['goods_note']) ? urldecode($orderData['goods_note']) : ""; //支付具体内容
            $order->trade_no    = $orderNo; //支付单号
            $order->out_trade_no = $orderData['order_id']; //商户单号
            $order->in_trade_no = "";
            $order->cnl_id = 0;
            $order->amount      = $orderData['order_amt']; //支付金额
            $order->pay_amount = $payAmount;
            $order->currency    = 'RMB'; //支付货币
            $order->channel     = $orderData['pay_type']; //支付渠道
            $order->client_ip   = $orderData['user_ip']; //订单创建IP
            $order->return_url  = !empty($orderData['return_url']) ? urldecode($orderData['return_url']) : ""; //通知Url
            $order->notify_url  = !empty($orderData['notify_url']) ? urldecode($orderData['notify_url']) : ""; //通知Url
            $order->extra       = !empty($orderData['extends']) ? urldecode($orderData['extends']) : ""; //拓展参数
            $order->save();
            Db::commit();

            //  余额 = 可用余额（可提现金额） + 冻结余额（待结算金额） =》 未支付金额每日清算
            //   可用余额是从冻结余额转入的
            //写入待支付金额 creatBalanceChange('100001','100',$remarks = '记录资金变动测试','字段',$setDec = true);
            //$this->logicBalanceChange->creatBalanceChange($order->uid, $order->amount, '单号' . $orderData['out_trade_no'] . '预下单支付金额', 'disable');

            return $order;
        } catch (\Exception $e) {
            //记录日志
            Log::error("Create Order Error:[{$e->getMessage()}]");
            Db::rollback();
            //抛出错误异常
            throw new OrderException([
                'msg'   =>  "Create Order Error, Please Try Again Later.",
                'errCode' => '200001'
            ]);
        }
    }

    /**
     * 设置某个字段参数
     *
     *
     * @param array $where
     * @param string $field
     * @param string $value
     */
    public function setOrderValue($where = [], $field = 'cnl_id', $value = '')
    {
        $this->modelOrders->setFieldValue($where, $field, $value);
    }
}
